package main

import (
	// "log"
	"flag"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/tsif/utils/encrypt"
)

var ARG_INPUTPATH = flag.String("input", "", "input file path")
var ARG_OUTPUTPATH = flag.String("output", "", "output file path")
var ARG_ENCRPY = flag.String("mode", "e", "encrpy")
var ARG_KEY = flag.String("key", "", "encrpy key")

func runA() {
	//运行参数
	fmt.Println("test os args", os.Args, len(os.Args))

	if len(os.Args) <= 1 {
		//os.Args = []string{"selfpath", "-input", "test/file.txt", "-output", "test/out.txt", "-mode", "e", "-key", "123"}
		os.Args = []string{"selfpath", "-input", "test/out.txt", "-output", "test/out_2.txt", "-mode", "d", "-key", "123"}
		fmt.Println("test os args", os.Args, len(os.Args))

	}

	// 输出
	//logStr := fmt.Sprint("args", os.Args, len(os.Args))
	//ioutil.WriteFile("log.txt", []byte(logStr), 0644)

	// 解析参数
	flag.Parse() // 需先构建参数再解析
	inputFilePath := *ARG_INPUTPATH
	outputFilePath := *ARG_OUTPUTPATH
	encrpy := *ARG_ENCRPY
	key := *ARG_KEY

	// 输出参数
	fmt.Printf("inputPath: \"%s\"\n", inputFilePath)
	fmt.Printf("outpthPath: \"%s\"\n", outputFilePath)
	fmt.Printf("encrypt: \"%s\"\n", encrpy)
	fmt.Printf("key: \"%s\"\n", key)
	if len(inputFilePath) <= 0 || len(outputFilePath) <= 0 || len(key) <= 0 {
		fmt.Printf("params fail! inputFilePath=%s, outputFilePath=%s, key=%s.\n", inputFilePath,
			outputFilePath,
			key)
		return
	}

	// 读取文件
	f_data, err_f := ioutil.ReadFile(inputFilePath)
	if err_f != nil {
		fmt.Printf("open file error! file=%s err=%s.\n", inputFilePath, err_f.Error())
		return
	}
	// fmt.Printf("file: \"%s\"", string(f_data))

	// 判断处理
	if encrpy == "e" {
		// 加密
		outStr, err_d := encrypt.AESEncrpyAndBase64(f_data, []byte(key))
		if err_d != nil {
			fmt.Printf("encrpy fail! %s\n", err_d.Error())
			return
		}
		// 输出
		err_out := ioutil.WriteFile(outputFilePath, []byte(outStr), 0644)
		if err_out != nil {
			fmt.Printf("file out fail! %s\n", err_out.Error())
			return
		}
		return
	}

	//解密
	d, err_d := encrypt.AESDecryptAndBase64(f_data, []byte(key))
	if err_d != nil {
		fmt.Printf("decrypt fail! %s\n", err_d.Error())
		return
	}
	// 输出
	err_out := ioutil.WriteFile(outputFilePath, []byte(d), 0644)
	if err_out != nil {
		fmt.Printf("file out fail! %s\n", err_out.Error())
		return
	}
}

const (
	EFILE_HEAD = "!@#$%^&"
	CMD_INPUT  = true
)

// 检测文件头
func CheckFileHead(f_data []byte, fileHeadStr string) bool {
	if len(f_data) < len(fileHeadStr) {
		return false
	}
	h_data := f_data[:len(fileHeadStr)]
	return string(h_data) == fileHeadStr
}

func runB() {
	if len(os.Args) <= 1 {
		// os.Args = []string{"selfpath", "test/out.txt"}
		os.Args = []string{"selfpath", "test/out.txt_encrypt"}
	}
	//运行参数
	fmt.Println("test os args", os.Args, len(os.Args))

	// 输入文件
	inputFilePath := os.Args[1]
	if len(inputFilePath) <= 0 {
		fmt.Printf("input file path is empty : %s\n", inputFilePath)
		return
	}

	// 读取文件
	f_data, err_f := ioutil.ReadFile(inputFilePath)
	if err_f != nil {
		fmt.Printf("open file error! file=%s err=%s.\n", inputFilePath, err_f.Error())
		return
	}

	// key处理
	var key string
	if CMD_INPUT {
		// 等待输入
		fmt.Printf("Please enter your key: ")
		n, err := fmt.Scanf("%s", &key)
		if err != nil {
			fmt.Println("input fail! ", err.Error(), n)
			return
		}
	} else {
		key = "123456"
	}

	// 检测头
	if CheckFileHead(f_data, EFILE_HEAD) {
		fmt.Printf("decrypt file : %s\n", string(f_data))
		outputFilePath := inputFilePath + "_decrypt"
		// 解密
		f_data_t := f_data[len(EFILE_HEAD):]

		//解密
		d, err_d := encrypt.AESDecryptAndBase64(f_data_t, []byte(key))
		if err_d != nil {
			fmt.Printf("decrypt fail! %s\n", err_d.Error())
			return
		}
		// 输出
		err_out := ioutil.WriteFile(outputFilePath, []byte(d), 0644)
		if err_out != nil {
			fmt.Printf("file out fail! %s\n", err_out.Error())
			return
		}
		return
	}
	// 加密处理
	fmt.Printf("encrypt file : %s\n", string(f_data))
	outputFilePath := inputFilePath + "_encrypt"

	// 加密
	outStr, err_d := encrypt.AESEncrpyAndBase64(f_data, []byte(key))
	if err_d != nil {
		fmt.Printf("encrpy fail! %s\n", err_d.Error())
		return
	}
	// 输出
	err_out := ioutil.WriteFile(outputFilePath, []byte(EFILE_HEAD+outStr), 0644)
	if err_out != nil {
		fmt.Printf("file out fail! %s\n", err_out.Error())
		return
	}

}

func main() {
	//runA()
	runB()
}
